package com.season.seasonStudy.javase.j_011_reflect;

import com.season.seasonStudy.javase.entity.Pet;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;


/**
 * 	反射 建立类的类型(3种方式)
 * 1.类名.class
 * 		Class cla = Pet.class;// class存的是类型
 * 2.对象.getclass
 *		Pet p =new Pet();
 *    	Class cla = p.getClass();
 * 3.根据路径
 *      Class cla = Class.forName("Need.Pet");	//这里需要对异常处理
 *	前面2个比较方便
 * 
 * cla.getName()
 * 		获得类的名字,带路径哦
 */

/**
 * --------类的属性:Field
 * cla.getDeclaredField(String fieldName);
 * 		返回特定field
 * 
 * cla.getDeclaredFields();
 * 		返回field数组
 * 
 * field.getName();
 * 		获得属性名字
 * 
 * field.getModifiers();
 * 		属性访问修饰符(用int数字表示,1~?)
 * Modifier.toString(field.getModifiers());
 * 		将属性访问修饰符变成我们能看懂的:private public....
 * 
 * field.getType();
 * 		属性类型,但是很长.eg. java.lang.String
 * field.getType().getSimpleName();
 * 		变简单,变短了	当然,基本数据类型不是对象,名字没长短都是一个
 */

/**
 * --------类的方法:Method
 * cla.getDeclaredMethod(String methodName,Class parameter);
 * 		这里别忘了写上参数
 * cla.getDeclaredMethods;
 * method.getName();
 * method.getModifiers();
 * Modifier,toString(method.getModifiers());
 * method.getReturnType();
 * 		获得返回值类型
 * method.getReturnType().getSimpleName();
 * 		变简单点
 * 
 *----方法是有参数的,下面就关于参数,不同地方哦-------- 
 * method.getParameterTypes();
 * 		获得参数列表
 * 	用一个Class接着,因为他们也是一个类
 * 	而且还得是数组
 * 
 */

/**
 * 杂乱点的?
 * 也许吧
 * 
 * Object o = cla.newInstance();
 * 		利用类(Class)建立新的对象
 * 
 * Method m = cla.getMethod("toString", new Class[] { 
 * 								int.class,String.class 
 * 								}
 * 							);
 * 
 * //这里之所以可以直接用pet方法，是因为不是o.xxx
			//而是，在将pet私有的东西送给了o了,赋值？还是送别人，还是？
			//设置对象 必不可少的
 */

/**
是什么？
反射包：reflect包

	原来是程序员自己定义对象
为什么？
	
用在哪？
	
怎么做？
##################################对象类型的解析#################
所需要的包是：reflect包
1、类的三种解析方法：

（1）Class als	Class。forName（“包名。类名”）；//用在框架
（2）Class	对象。getClass（）；//用在框架
（3）Class	类名。class；//用在传参


2、类下比较重要的方法

class   。getSimpleName（）
	。getFields（）获取所有的属性，不包括public权限以下的方法
	。getMethods（）获取所有的方法，不包括public权限以下的方法
	。getConstructor（）获取所有构造方法，不包括public权限以下的方法

	。getDeclareFields（）获取所有属性，包括不是比public权限小的
	。getDeclareMethods（）获取所有方法，包括不是比public权限小的
	。getDeclareConstructor（）获取所有构造方法，根据参数列表获取构造方法！，包括不是比public权限小的

	。getDeclaredMethod("setName", String.class);当然有获取特殊的一个，不是全部的方法！这种必须知道方法名，参数值类型！！！！



注意：
	成员变量是public权限以下的权限的，必须用方法打开权限。是public的不用！！
      （1）想要获取出成员变量给他赋值的话，一般的都是要用class。getField（）方法获得field，然后再用field。setAccessible（true）方法获取权限！给附上值！！！
      （2）在公共类方法里，要遍历着给成员变量赋值的话，一定要用class。getDeclareFields（）方法取field，然后再用field。setAccessible（true）方法获取权限！然后再赋值！！！

##################################创建出对象#################


class   。newInstance();这句话创建出你解析出来的类的对象！！！！！
	。getDeclareFields（fieldName）根据属性名获取属性
	。getDeclareMethods（方法名，参数类型列表）
	。getDeclareConstructor（参数类型列表）




##################################属性的解析#################

field	。getName（）获取属性姓名
	。getType（）获取属性类型
	。getModifiers（）获取属性的修饰符
	。getAccessible（true）允许访问
	。set（对象，值）设置当前定义的属性的值
	。get（对象）获取当前定义的属性的值

################################方法的解析#################
Method【】	cls。获取类方法
	

method	。getName（）获取方法名
	。getModifiers（）获取修饰符
	。getParameterTypes（）获取方法参数类型列表
	。getReturnTypes（）获取方法返回值类型
        。invoke（对象，实参值）返回的是方法返回值

################################构造方法的解析#################
Construct【】	cls。获取构造方法！


construct。getName（）获取方法名
	。getModifiers（）获取方法修饰符
	。getParameterTypes（）获取方法参数类型列表
	。newInstance（参数值）调用类的构造方法并传入对应实际参数值，返回当前的实例


################################Array数组的解析#################

Array。newlnstance（类型，空间数），创建类型是第一个参数的长度是第二个参数的数组
     。newlnstance（类型，int。。。）创建多维数组，从那后俗子是每一个ie层次存储个数
     。set***（数组对象，位置，值）基本数据类型方法给数组的某个位置元素赋值
     。set（数组对象，位置，值）引用数据类型方法给数组的某个位置元素赋值

*/




public class ReflactDemo {
	public static void main(String[] args) {

		Class cla = Pet.class;// class存的是类型

		
		System.out.println(cla.getName());
		
		//获得属性Field
		Field[] fields = cla.getDeclaredFields();// 返回field数组
		System.out.println("Feild----------------------");
		for (Field field : fields) {
			
			System.out.println(field.getName());
			
			System.out.println(field.getModifiers());
			System.out.println(Modifier.toString(field.getModifiers()));
			
			System.out.println(field.getType());
			System.out.println(field.getType().getSimpleName());
			
			System.out.println("+++++++++++++++++++++++++++++++++");
		}
		System.out.println("---------------------------");
		System.out.println("\n\n\n\n\n\n\n");



		
		//获得方法Method
		Method[] methods = cla.getDeclaredMethods(); // 所有方法
		System.out.println("Method---------------------");
		for (Method method : methods) {
			System.out.println(method.getName());
			
			System.out.println(method.getModifiers());
			System.out.println(Modifier.toString(method.getModifiers()));
			
			System.out.println(method.getReturnType());
			System.out.println(method.getReturnType().getSimpleName());
			
			Class[] cls = method.getParameterTypes();
			for (Class a : cls) {
				System.out.println("-----参数类型：" + a.getName());
			}
			System.out.println("+++++++++++++++++++++++++++++++++++");
		}
		
		
		try {
			
			Object o = cla.newInstance();
			//这里之所以可以直接用pet方法，是因为不是o.xxx
			//而是，在将pet私有的东西送给了o了,赋值？还是送别人，还是？
			//设置对象 必不可少的
			
			Method m = cla.getMethod("show", new Class[]{ int.class,//这里用的是一个可变数组
					String.class });
			
			Object[] values = { 10, "aaaa" };
			//使用反射创建实例，用method invoke执行方法
			m.invoke(o, values);
			
			Field f = cla.getDeclaredField("name");
//			f.set(o, "小白白");//对类的field设置新的属性,当然这是操作对象的
			
			f.setAccessible(true);//私有的，进行设置
			f.set(o,"xiaobaibai");
			
			Method m1 = cla.getDeclaredMethod("getAge", null);
			System.out.println(m1.invoke(o, null));
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
